package com.aabte.spring.annotation.config;

import com.aabte.spring.listener.ListenerByMethodAnnotation;
import com.aabte.spring.listener.MyApplicationListener;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.EventListenerMethodProcessor;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;

import java.util.concurrent.Executor;

/**
 * {@link ApplicationListener}：监听容器中发布的事件，事件驱动模型开发
 *
 * 监听事件：
 *  １、实现{@link ApplicationListener#onApplicationEvent(ApplicationEvent)}监听者接口，泛型为要监听的事件类型
 *  ２、将监听者注入到容器中
 *
 * 发布事件：
 *  1、获取IOC容器对象{@link ApplicationContext}
 *  2、调用{@link ApplicationContext#publishEvent}方法发布事件
 *  3、对应的{@link ApplicationListener}监听者会被回调
 *
 * 事件多播器的初始化：
 *  1、创建IOC容器
 *  2、初始化事件多播器{@link AbstractApplicationContext#initApplicationEventMulticaster()} {@link AbstractApplicationContext#publishEvent(Object)}
 *      1、优先从容器中获取{@link AbstractApplicationContext#APPLICATION_EVENT_MULTICASTER_BEAN_NAME}组件，如果有直接使用
 *      2、如果没有，则创建{@link SimpleApplicationEventMulticaster}组件
 *  3、注册监听器对象 {@link AbstractApplicationContext#registerListeners()}
 *      1、从容器中获取所有{@link ApplicationListener}组件
 *      2、把{@link ApplicationListener}组件注册到事件多播器中{@link ApplicationEventMulticaster}
 *
 * 异步发布事件：{@link TaskExecutor}
 *  1、{@link SyncTaskExecutor}
 *  2、{@link AsyncTaskExecutor}
 *
 * Spring发布事件流程：
 *  1、创建IOC容器
 *  2、容器刷新完成
 *  3、发布事件 {@link AbstractApplicationContext#publishEvent(Object)}
 *      1、获取事件的多播器（派发器） {@link AbstractApplicationContext#getApplicationEventMulticaster}
 *      2、派发事件 {@link SimpleApplicationEventMulticaster#multicastEvent}
 *          1、获取所有的{@link ApplicationListener}监听者对象
 *          2、遍历所有监听者{@link ApplicationListener}对象
 *              1、判断是否有{@link Executor}对象（支持异步派发），如果支持使用多线程派驻发
 *              2、否则直接执行{@link SimpleApplicationEventMulticaster#invokeListener}方法，回调监听者{@link ApplicationListener#onApplicationEvent(ApplicationEvent)}方法
 *
 * {@link EventListenerMethodProcessor}实现原理：
 *  1、创建IOC容器，并刷新容器
 *  2、初始化所有剩下的单实例Bean {@link AbstractApplicationContext#finishBeanFactoryInitialization}
 *      1、先创建所有的单实例Bean
 *      2、获取所有创建好的单实例Bean，判断是否是{@link SmartInitializingSingleton}类型
 *         如果是就回调{@link SmartInitializingSingleton#afterSingletonsInstantiated()}方法
 *
 * @author Daniel
 */
@Configuration
public class ApplicationListenerConfig {

    @Bean
    public ApplicationListener myApplicationListener() {
        return new MyApplicationListener();
    }

    @Bean
    public ListenerByMethodAnnotation listenerByMethod(){
        return new ListenerByMethodAnnotation();
    }

}
